package com.h3c.web.support.cas;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.jasig.cas.CentralAuthenticationService;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.services.RegisteredService;
import org.jasig.cas.services.ServicesManager;
import org.jasig.cas.services.UnauthorizedServiceException;
import org.jasig.cas.ticket.Ticket;
import org.jasig.cas.ticket.TicketGrantingTicket;
import org.jasig.cas.web.support.ArgumentExtractor;
import org.jasig.cas.web.support.CookieRetrievingCookieGenerator;
import org.jasig.cas.web.support.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException;

import com.h3c.dal.common.TableConstant;
import com.h3c.dal.dao.CasssoSystemDAO;
import com.h3c.dal.dao.CasssoUserDAO;
import com.h3c.dal.entity.CasssoSystemDO;
import com.h3c.dal.entity.CasssoUserDO;
import com.h3c.dal.entity.query.CasssoSystemQuery;
import com.h3c.dal.entity.query.CasssoUserQuery;
import com.h3c.web.common.utils.ListUtil;

/**
 * @ClassName: InitialFlowSetupAction
 * @Description: 实现多组织
 * @author: d14287
 * @date: 2017年6月2日 下午1:51:10
 */
public class InitialFlowSetupAction extends AbstractAction {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	/** The services manager with access to the registry. **/
	@NotNull
	private ServicesManager servicesManager;
	/** CookieGenerator for the Warnings. */
	@NotNull
	private CookieRetrievingCookieGenerator warnCookieGenerator;
	/** CookieGenerator for the TicketGrantingTickets. */
	@NotNull
	private CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator;
	@Autowired
	private CentralAuthenticationService centralAuthenticationService;
	@Autowired
	private CasssoUserDAO casssoUserDAO;
	@Autowired
	private CasssoSystemDAO casssoSystemDAO;
	/** Extractors for finding the service. */
	@NotNull
	@Size(min = 1)
	private List<ArgumentExtractor> argumentExtractors;
	/**
	 * Boolean to note whether we've set the values on the generators or not.
	 */
	private boolean pathPopulated;
	/**
	 * If no authentication request from a service is present, halt and warn the user.
	 */
	private boolean enableFlowOnAbsentServiceRequest = true;

	@SuppressWarnings("unchecked")
	@Override
	protected Event doExecute(final RequestContext context) throws Exception {
		final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
		if (!this.pathPopulated) {
			final String contextPath = context.getExternalContext().getContextPath();
			final String cookiePath = StringUtils.hasText(contextPath) ? contextPath + '/' : "/";
			logger.info("Setting path for cookies to: {} ", cookiePath);
			this.warnCookieGenerator.setCookiePath(cookiePath);
			this.ticketGrantingTicketCookieGenerator.setCookiePath(cookiePath);
			this.pathPopulated = true;
		}
		WebUtils.putTicketGrantingTicketInScopes(context,
				this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request));
		WebUtils.putWarningCookie(context, Boolean.valueOf(this.warnCookieGenerator.retrieveCookieValue(request)));
		Service temService = WebUtils.getService(this.argumentExtractors, context);
		if (temService != null) {
			final String tgtId = WebUtils.getTicketGrantingTicketId(context);
			if (StringUtils.hasText(tgtId)) {
				final Ticket ticket = this.centralAuthenticationService.getTicket(tgtId, Ticket.class);
				if (ticket != null && !ticket.isExpired()) {
					TicketGrantingTicket serviceTicket = (TicketGrantingTicket) ticket;
					String loginId = serviceTicket.getAuthentication().getPrincipal().getId();
					CasssoUserQuery userQuery = new CasssoUserQuery();
					userQuery.createCriteria().andLoginIdEqualTo(loginId)
							.andStatusEqualTo(TableConstant.USER_STATUS_ACTIVATED);
					List<CasssoUserDO> userList = casssoUserDAO.selectByExample(userQuery);
					if (ListUtil.isNotEmpty(userList)) {
						String curentOuId = userList.get(0).getOuId();
						CasssoSystemQuery sysQuery = new CasssoSystemQuery();
						sysQuery.createCriteria().andOuIdEqualTo(curentOuId)
								.andStatusEqualTo(TableConstant.COMMON_STATUS_NORMAL);
						List<CasssoSystemDO> sysList = casssoSystemDAO.selectByExample(sysQuery);
						// 不属于同一个组织则把temServer置为空,flag=false不属于同一个组织
						boolean flag = false;
						for (CasssoSystemDO casssoSystemDO : sysList) {
							if (temService.getId().startsWith(casssoSystemDO.getUrl())) {
								flag = true;
								break;
							}
						}
						if (!flag) {
							temService = null;
						}
					}
				}
			}
		}
		final Service service = temService;
		if (service != null) {
			logger.debug("Placing service in context scope: [{}]", service.getId());
			final RegisteredService registeredService = this.servicesManager.findServiceBy(service);
			if (registeredService != null && registeredService.getAccessStrategy().isServiceAccessAllowed()) {
				logger.debug("Placing registered service [{}] with id [{}] in context scope",
						registeredService.getServiceId(), registeredService.getId());
				WebUtils.putRegisteredService(context, registeredService);
			}
		} else if (!this.enableFlowOnAbsentServiceRequest) {
			logger.warn(
					"No service authentication request is available at [{}]. CAS is configured to disable the flow.",
					WebUtils.getHttpServletRequest(context).getRequestURL());
			throw new NoSuchFlowExecutionException(context.getFlowExecutionContext().getKey(),
					new UnauthorizedServiceException("screen.service.required.message", "Service is required"));
		}
		WebUtils.putService(context, service);
		return result("success");
	}
	public void setTicketGrantingTicketCookieGenerator(
			final CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator) {
		this.ticketGrantingTicketCookieGenerator = ticketGrantingTicketCookieGenerator;
	}
	public void setWarnCookieGenerator(final CookieRetrievingCookieGenerator warnCookieGenerator) {
		this.warnCookieGenerator = warnCookieGenerator;
	}
	public void setArgumentExtractors(final List<ArgumentExtractor> argumentExtractors) {
		this.argumentExtractors = argumentExtractors;
	}
	/**
	 * Set the service manager to allow access to the registry to retrieve the registered service
	 * details associated with an incoming service. Since 4.1
	 * @param servicesManager the services manager
	 */
	public void setServicesManager(final ServicesManager servicesManager) {
		this.servicesManager = servicesManager;
	}
	/**
	 * Decide whether CAS should allow authentication requests when no service is present in the
	 * request. Default is enabled.
	 * @param enableFlowOnAbsentServiceRequest the enable flow on absent service request
	 */
	public void setEnableFlowOnAbsentServiceRequest(final boolean enableFlowOnAbsentServiceRequest) {
		this.enableFlowOnAbsentServiceRequest = enableFlowOnAbsentServiceRequest;
	}
}
